package com.xinz.srmi.impl;

import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import com.xinz.srmi.Buffer;
import com.xinz.srmi.ByteArrayInputStream;
import com.xinz.srmi.ByteArrayOutputStream;
import com.xinz.srmi.NativeMethod;
import com.xinz.srmi.Serializer;
import com.xinz.srmi.Session;
import com.xinz.srmi.impl.serialization.BeanInputStream;
import com.xinz.srmi.impl.serialization.BeanOutputStream;
/**
 * 返回时候使用zip压缩
 * @author xingyun
 *
 */
public class ZipBinarySerializer implements Serializer {

	
	@Override
	public Buffer methodToBuffer(Session session, Method method,Object header, Object[] args) {
		//从共享上下文里获取方法的ID
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		BeanOutputStream bos = session.createOutputStream(baos);
		String methodName = method.getName();
		String interfaceName = method.getDeclaringClass().getName();
		int id = session.getRomateMethodId(interfaceName,methodName);
		
		try {
			if(id<0){
				id = session.saveRomateMethod(method);
				bos.writeShort(-1);
				bos.writeShort(id);
				bos.writeUTF(interfaceName);
				bos.writeUTF(methodName);
			}else{
				bos.writeShort(id);
			}
			bos.writeObject(header);
			bos.writeObject(args);
		} catch (Exception e) {
			throw new Error(e.getMessage());
		}
		return baos.toBuffer();
	}

	@Override
	public NativeMethod parseMethod(Session session, Buffer request) {
		BeanInputStream is =  session.createInputStream(request.asInputStream());
		try {
			int index = is.readShort();
			Method method;
			if(index<0){
				int id = is.readShort();
				String interfaceName = is.readUTF();
				String methodName = is.readUTF();
				int saveId = session.saveNativeMethod(interfaceName,methodName);
				assert id==saveId:"读取方法：";
				method = session.getNativeMethod(interfaceName,methodName);
			}else{
				method = session.getNativeMethod(index);
			}
			Object header = is.readObject();
			Object args[] = (Object[]) is.readObject();
			return new NativeMethod(method, args,header);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
	}
	@Override
	public Buffer returnToBuffer(Session session,Object header, Object result,
			boolean isException) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ZipOutputStream zos = new ZipOutputStream(baos);
		BeanOutputStream bos = session.createOutputStream(zos);
		try {
			zos.putNextEntry(new ZipEntry("z"));
			bos.writeObject(header);
			bos.writeBoolean(isException);
			bos.writeObject(result);
		} catch (Exception e) {
			throw new Error(e.getMessage());
		}finally{
			try {
				zos.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		return baos.toBuffer();
	}
	@Override
	public Object parseReturn(Session session, Buffer result,
			Object[] responseHeader) throws Throwable {
		ZipInputStream zis = new ZipInputStream(result.asInputStream());
		zis.getNextEntry();
		BeanInputStream is = session.createInputStream(zis);
		try {
			responseHeader[0] = is.readObject();
			boolean isException = is.readBoolean();
			Object obj = is.readObject();
			if(isException){
				throw (Throwable)obj;
			}else{
				return obj;
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}finally{
			zis.close();
		}
	}


	

}
